
package pers.rcl.common.util;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigInteger;
import java.net.InetAddress;
import java.util.Calendar;
import java.util.UUID;

/**
 * 全局唯一编号生成工具
 */
public class SeqUtil {
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    private static String ipStr;
    private static SeqUtil SEQUTIL_ORDERNO = new SeqUtil();

    private SeqUtil() {
        try {
            ipStr = InetAddress.getLocalHost().getHostAddress();
            ipStr = ipStr.substring(ipStr.indexOf("." + 1)).replace(".", "");
            if (ipStr.length() > 5) {
                ipStr = ipStr.substring(ipStr.length() - 5);
            } else {
                ipStr = RandomStringUtils.randomNumeric(5);
            }

        } catch (Exception e) {
            ipStr = RandomStringUtils.randomNumeric(5);
        }
    }

    public static SeqUtil getSeqInstance() {
        return SEQUTIL_ORDERNO;
    }

    public static String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public String nextSeq(String prefix) {
        return prefix + nextSeq();
    }

    public synchronized String nextSeq() {

        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence += 1;
            if (sequence == 999) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(timestamp);

        int year = c.get(Calendar.YEAR) % 100; // 2位
        int month = c.get(Calendar.MONTH); // 2位
        int day = c.get(Calendar.DATE); // 2位
        int hour = c.get(Calendar.HOUR); // 2位
        int min = c.get(Calendar.MINUTE); // 2位
        int sec = c.get(Calendar.SECOND); // 2位
        int mil = c.get(Calendar.MILLISECOND); // 3位

        String format = String.format("%02d%02d%02d%02d%02d%02d%5s%03d%03d", year, month + 1, day, hour, min, sec, ipStr, sequence, mil);
        return format;
    }

    /**
     * @return
     * @// TODO: 2020/5/11  由年月日时分秒+根据本机ip+3位随机数 生成流水号
     * old remark 由年月日时分秒+3位随机数 生成流水号
     */
    public static String createBillNo() throws Exception {
        //本机ip+
        InetAddress ia = InetAddress.getLocalHost();
        String ip = ia.getHostAddress();
        int x = (int) (Math.random() * 900) + 100;
        int re = new BigInteger(MD5.MD5Encode(StringUtils.join(ip, x)).getBytes()).intValue();

        String t = LocalDateUtils.getDateTimeStrForNow();
        String billNo = t + re;
        return billNo;
    }

    /**
     * 生成Long（可作为id使用）
     *
     * @return
     * @throws Exception
     */
    public static Long createId() throws Exception {
        return new BigInteger(MD5.MD5Encode(createBillNo()).getBytes()).longValue();
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }
}
